package com.lottery.service;

import com.lottery.model.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

@Service
@Slf4j
public class LotteryService {
    //默认路口
    private final String DEFAULT_URL = "https://webapi.sporttery.cn/gateway/lottery/getFootBallMatchV1.qry?param=90,0&lotteryDrawNum=&sellStatus=0&termLimits=10";

    public List<Match> getMatches(String url, String drawNum) {
        try {
            String requestUrl = url == null || url.trim().isEmpty() ? DEFAULT_URL : url.trim();
            // 如果提供了期号，覆盖URL中的期号参数
            if (drawNum != null && !drawNum.trim().isEmpty()) {
                //专门的期号路口
                requestUrl = "https://webapi.sporttery.cn/gateway/lottery/getFootBallMatchV1.qry?param=90,0&lotteryDrawNum="+drawNum.trim()+
                        "&sellStatus=0" ;
            }
            WebClient webClient = WebClient.builder()
                    .defaultHeader("User-Agent", getRandomUserAgent())
                    .defaultHeader("Accept", "application/json, text/javascript, */*; q=0.01")
                    .defaultHeader("X-Requested-With", "XMLHttpRequest")
                    .build();

            Map<String, Object> response = webClient.get()
                    .uri(requestUrl)
                    .retrieve()
                    .bodyToMono(Map.class)
                    .block();

            if (response == null || !Boolean.TRUE.equals(response.get("success"))) {
                String errorMsg = (String) response.getOrDefault("errorMessage", "未知错误");
                throw new RuntimeException("API返回错误: " + errorMsg);
            }

            Map<String, Object> value = (Map<String, Object>) response.get("value");
            Map<String, Object> sfcMatch = (Map<String, Object>) value.get("sfcMatch");
            List<Map<String, Object>> matchList = (List<Map<String, Object>>) sfcMatch.get("matchList");

            if (matchList == null || matchList.isEmpty()) {
                return getDefaultMatchData();
            }

            List<Match> matches = new ArrayList<>();
            for (int i = 0; i < Math.min(14, matchList.size()); i++) {
                Map<String, Object> matchData = matchList.get(i);
                matches.add(parseMatch(matchData, i + 1));
            }

            // 确保有14场比赛
            while (matches.size() < 14) {
                matches.add(getDefaultSingleMatch(matches.size() + 1));
            }

            return matches;
        } catch (Exception e) {
            log.info(e.getMessage());
            return getDefaultMatchData();
        }
    }

    // 修复比赛时间解析问题
    private Match parseMatch(Map<String, Object> matchData, int index) {
        Match match = new Match();
        match.setId(index);
        match.setLeague((String) matchData.getOrDefault("matchName", "未知联赛"));

        // 修复时间解析逻辑 - 从不同字段获取时间
        String startTime = (String) matchData.getOrDefault("startTime", "");
        // 尝试从另一个可能的时间字段获取
        if (startTime == null || startTime.isEmpty()) {
            startTime = (String) matchData.getOrDefault("matchTime", "");
        }

        if (startTime != null && startTime.length() >= 16) {
            String datePart = startTime.substring(5, 10);
            String timePart = startTime.substring(11, 16);
            match.setTime(datePart + " " + timePart);
        } else if (startTime != null && !startTime.isEmpty()) {
            match.setTime(startTime);
        } else {
            // 如果没有时间数据，使用默认格式
            match.setTime(String.format("08-%02d 20:00", index + 10));
        }

        match.setHome((String) matchData.getOrDefault("masterTeamName", "主队" + index));
        match.setAway((String) matchData.getOrDefault("guestTeamName", "客队" + index));

        try {
            match.setOdds3(parseOdds(matchData.get("h"), 1.5));
            match.setOdds1(parseOdds(matchData.get("d"), 3.5));
            match.setOdds0(parseOdds(matchData.get("a"), 5.5));
        } catch (Exception e) {
            match.setOdds3(round(1.5 + ThreadLocalRandom.current().nextDouble(), 2));
            match.setOdds1(round(3.5 + ThreadLocalRandom.current().nextDouble(), 2));
            match.setOdds0(round(5.5 + ThreadLocalRandom.current().nextDouble() * 2, 2));
        }

        return match;
    }


    private double parseOdds(Object oddsObj, double minValue) {
        if (oddsObj == null) {
            return round(minValue + ThreadLocalRandom.current().nextDouble(), 2);
        }
        try {
            return round(Double.parseDouble(oddsObj.toString()), 2);
        } catch (NumberFormatException e) {
            return round(minValue + ThreadLocalRandom.current().nextDouble(), 2);
        }
    }
    
    private double round(double value, int places) {
        if (places < 0) throw new IllegalArgumentException();
        long factor = (long) Math.pow(10, places);
        value = value * factor;
        long tmp = Math.round(value);
        return (double) tmp / factor;
    }
    
    public String getRandomUserAgent() {
        List<String> userAgents = Arrays.asList(
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15"
        );
        return userAgents.get(ThreadLocalRandom.current().nextInt(userAgents.size()));
    }
    
    public List<Match> getDefaultMatchData() {
        return IntStream.rangeClosed(1, 14)
                .mapToObj(this::getDefaultSingleMatch)
                .collect(Collectors.toList());
    }
    
    public Match getDefaultSingleMatch(int idx) {
        return new Match(
            idx,
            "联赛" + idx,
            String.format("08-%02d 20:00", idx + 10),
            "主队" + idx,
            "客队" + idx,
            round(1.2 + ThreadLocalRandom.current().nextDouble(), 2),
            round(3.0 + ThreadLocalRandom.current().nextDouble(), 2),
            round(4.0 + ThreadLocalRandom.current().nextDouble() * 3, 2)
        );
    }

    public CombinationResult generateCombinations(CombinationRequest request) {
        List<SelectedMatch> validSelections = request.getSelectedMatches().stream()
                .filter(sm -> sm.isSelect3() || sm.isSelect1() || sm.isSelect0())
                .collect(Collectors.toList());

        if (validSelections.size() < 9 || validSelections.size() > 14) {
            throw new IllegalArgumentException("请选择9-14场比赛");
        }

        // 获取所有比赛数据（用于匹配赔率）
        List<Match> allMatches = getMatches(null,null);

        // 生成组合逻辑
        List<List<SelectedMatch>> combinations = generate9FromN(validSelections);

        // 转换为结果格式（添加赔率信息）
        List<List<MatchSelection>> resultCombinations = new ArrayList<>();
        for (List<SelectedMatch> combo : combinations) {
            List<MatchSelection> matchSelections = new ArrayList<>();
            for (SelectedMatch sm : combo) {
                MatchSelection ms = new MatchSelection();
                ms.setMatchId(sm.getMatchId());

                // 获取对应的比赛数据（包含赔率）
                Match matchInfo = allMatches.stream()
                        .filter(m -> m.getId().equals(sm.getMatchId()))
                        .findFirst()
                        .orElse(null);

                if (matchInfo != null) {
                    ms.setHome(matchInfo.getHome());
                    ms.setAway(matchInfo.getAway());
                    ms.setLeague(matchInfo.getLeague()); // 设置联赛信息
                    ms.setOdds3(matchInfo.getOdds3());  // 设置胜赔
                    ms.setOdds1(matchInfo.getOdds1());  // 设置平赔
                    ms.setOdds0(matchInfo.getOdds0());  // 设置负赔
                } else {
                    ms.setHome("主队" + sm.getMatchId());
                    ms.setAway("客队" + sm.getMatchId());
                    ms.setLeague("未知联赛"); // 默认联赛信息
                    ms.setOdds3(1.0);
                    ms.setOdds1(1.0);
                    ms.setOdds0(1.0);
                }

                List<String> selections = new ArrayList<>();
                if (sm.isSelect3()) {
                    selections.add("3");
                }
                if (sm.isSelect1()) {
                    selections.add("1");
                }
                if (sm.isSelect0()) {
                    selections.add("0");
                }
                ms.setSelections(selections);

                matchSelections.add(ms);
            }
            resultCombinations.add(matchSelections);
        }

        // 计算总注数和金额
        long totalBets = calculateTotalBets(validSelections, combinations);

        return new CombinationResult(
                resultCombinations,
                combinations.size(),
                totalBets,
                totalBets * 2.0 // 每注2元
        );
    }
    
    private List<List<SelectedMatch>> generate9FromN(List<SelectedMatch> list) {
        List<List<SelectedMatch>> result = new ArrayList<>();
        combinations(list, 9, 0, new ArrayList<>(), result);
        return result;
    }
    
    private void combinations(List<SelectedMatch> list, int k, int start, 
                             List<SelectedMatch> current, List<List<SelectedMatch>> result) {
        if (current.size() == k) {
            result.add(new ArrayList<>(current));
            return;
        }
        
        for (int i = start; i < list.size(); i++) {
            current.add(list.get(i));
            combinations(list, k, i + 1, current, result);
            current.remove(current.size() - 1);
        }
    }

    public long calculateTotalBets(List<SelectedMatch> validSelections, List<List<SelectedMatch>> combinations) {
        long totalBets = 0;

        // 为每个组合计算注数
        for (List<SelectedMatch> combo : combinations) {
            int comboBets = 1;

            // 计算单场比赛的选择数并相乘
            for (SelectedMatch match : combo) {
                int choices = 0;
                if (match.isSelect3()) {
                    choices++;
                }
                if (match.isSelect1()) {
                    choices++;
                }
                if (match.isSelect0()) {
                    choices++;
                }

                // 至少有一个选择（前面已验证）
                comboBets *= choices;
            }

            totalBets += comboBets;
        }

        return totalBets;
    }

    public List<String> getRecentDrawNumbers() {
        try {
            WebClient webClient = WebClient.builder()
                    .defaultHeader("User-Agent", getRandomUserAgent())
                    .build();

            Map<String, Object> response = webClient.get()
                    .uri("https://webapi.sporttery.cn/gateway/lottery/getFootBallMatchV1.qry?param=90,0&sellStatus=1&termLimits=10")
                    .retrieve()
                    .bodyToMono(Map.class)
                    .block();

            if (response == null || !Boolean.TRUE.equals(response.get("success"))) {
                return getDefaultDrawNumbers();
            }

            Map<String, Object> value = (Map<String, Object>) response.get("value");
            List<String> terms = (List<String>) value.get("sfclist");

            if (terms == null || terms.isEmpty()) {
                return getDefaultDrawNumbers();
            }

            return terms;
        } catch (Exception e) {
            log.info(e.getMessage());
            return getDefaultDrawNumbers();
        }
    }

    private List<String> getDefaultDrawNumbers() {
        List<String> defaults = new ArrayList<>();
        Calendar cal = Calendar.getInstance();
        int year = cal.get(Calendar.YEAR) % 100; // 取年份后两位

        for (int i = 10; i > 0; i--) {
            defaults.add(String.format("%d%03d", year, i));
        }
        return defaults;
    }
}